
import com.pay.ddpay.bean.ClientRequestData;
import com.pay.ddpay.bean.ClientResponseData;
import com.pay.ddpay.bean.TradeDetail;
import com.pay.ddpay.common.ETranState;
import com.pay.ddpay.common.util.DateTimeUtils;
import com.pay.ddpay.common.util.HttpClientFactory;
import com.pay.ddpay.common.util.JsonUtils;
import com.pay.ddpay.paysign.Base64;
import com.pay.ddpay.paysign.RSAHelper;

import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;

import static com.pay.ddpay.paysign.RSAHelper.getPrivateKey;
import static com.pay.ddpay.paysign.RSAHelper.getPublicKey;

public class DaifuTest {

    //static String svr_url = "http://localhost:8890/trade";
    static String svr_url = "http://pay.0afo.top/ddpay/trade";

    String public_key="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw/Z2airKp9MKL+gHVwUoGp46BNodkftoUAeIikmkFY7v56mK1KhJVDHz5KBHDMehzWExJVHt1lhabilsImWv0Vd92UaBo7r3I3XDGGnBkumV/i3QfV510xR25TgRVqESG8r2uGVbA8FtEoIq4IVm4Fcjf5fKwrIlqH+A0YoLOHy6AFZKK1VU/ShgRj4WCzRJqFY6HcLsiJsxUqD4FAyRoSDcFNtqP9Of2j6vspCxJmkeeBQc0/y5SCHqmzTjYRooIObuBmwydB1A4+oR2MEswl15OLPkEry/iB8RzyMimAHU+sE8OczqPOxJ8YDGuAUTODhTKA3G+ZaJLFNideFqYwIDAQAB";
    static String private_key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDD9nZqKsqn0wov6AdXBSganjoE2h2R+2hQB4iKSaQVju/nqYrUqElUMfPkoEcMx6HNYTElUe3WWFpuKWwiZa/RV33ZRoGjuvcjdcMYacGS6ZX+LdB9XnXTFHblOBFWoRIbyva4ZVsDwW0SgirghWbgVyN/l8rCsiWof4DRigs4fLoAVkorVVT9KGBGPhYLNEmoVjodwuyImzFSoPgUDJGhINwU22o/05/aPq+ykLEmaR54FBzT/LlIIeqbNONhGigg5u4GbDJ0HUDj6hHYwSzCXXk4s+QSvL+IHxHPIyKYAdT6wTw5zOo87EnxgMa4BRM4OFMoDcb5loksU2J14WpjAgMBAAECggEAO7ZkSuGTMyRpnEN1yRx3JfVE9KmKDSuwk4JYJttdtnwBunO9LCPDhHZcPTRhshE6ypxtH1QhxwjRNXRF0Q1vT7j7TjPf2QZlvFZsBopjQ+MNo5BOUYVxHcrEmABHuEAIhpOILpQj8bcFB3jGm/fKa13iIUUdscobE4cWt8L6vFEsqpuvQLYz0vv/AYWsnBJxrJooUFCqb8YdygRwnQzDZw6bTMvYDhnEQdvWSKl/QCyKZobR/5SFuoDmHTDzId+DeBJcrSFY4VjuO1tn8GzE0fv1kNXxCZECqqrILAbe1AM5YrGn+lUjQ4hXc92Tc/81IKyj14Sr7G7rWVakx55cYQKBgQDrLUkUfvpwwH9awVkjHXuRrONmsxF7Jrlrv/BIlDykMjitdNrtULml///rXqs0J8u1iQclzTKX9HSr6g74HnKvtxGgaNIxbfVT2DuEKJAY4haxVjUE6glXSCWbW3YzY2RQpeFWGqBISGQS17t//CDMtjFw+gj68lOhfxxYGRNf+QKBgQDVUFENAW4wwKY6IqoohCeOlp1ZKqK+D7Qdgt5JzEy6zLE7/YQujtTTEPtpsHrOyRWfCvsdJVF8BcdwgaBdNne2378kWB79lF/6HhhLpU/afNCecVwBSkLM1W2YGtMtD0+ITnouuuNWY9v9NNTmG6sjdi9VmiEpB9CI3L+xIyesOwKBgHYf+vMWjIiRx+Y386PVrTmQk3AERaWL39qlP/XUr1jx+NH3Pfexcm5U1aDNnkTGMGXwe+ya0uzMVsX6/KXX9VcZJvthayJ0zqLcm5hYH3jAJxHP8TWUsDhs/qa4G/jX1Y1EpJhxK0zjP5DPV1iDtZ3dbZwHmvchPKyDgiMmBTtRAoGBAJ3yAHGO05ZJr0twi2nAoMGViCCTzzjHy+fmFM2z9kSCd+EhkBQhMjiuZFoXkHc4sUe4C8PC9BjO9qO5d5JNWEsSVSeGEDxW9tHuIrMwTnZK4PXQnf1ejSO6DJIJmr/MjGkzIokjXF2FR0ivK8zOQ+PYCKhrnY4R+Ti9qzpv+1otAoGBANdJEJxl+oSuMPhYNcWJTYbCYqx+IOD5jLjcHBpDYm2O+d0AiAITOFqgTy+Uhdhm0J1aeNuTcD/5nZRfSDxCpgdWp1zp1ggN8VA1ZlODzYWtUAQova/3De4fvG/DHuqGQXZEx2//oaD3+gHCNbqoJVFsVNkWS2mYNAhzEIQgA2j2";
    static String platform_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsGX2DfdTLKo2UejvurhnIcLSAWMRB8q6walkCYbDAsDwT/WPRXxuYH+dPW08X5fmaCMnM/8I1/Z/Merdl1UU8E39vtNnHN9Lr86G/Bybuf78ziNAQQ979LWh+XqOvtWAOE32EoJRoYjqo9uYWnhjwHJA6bzdIEcfRxOvDqOyPxqDoWcqg8Uv69xmo1Uyo3FxDK1zVBUkRBH3RZZ6uiBezOSG6yQuVsW7HY7/LXoySQ1ADTVxC2zZB+OoCFskJcTtFFxhVSylIoWQl34BTERtvDWmAD3XkzSPWNRfaPwXpr1u07W3rwthL7UhcKGCiaFsQTB1cd+bFXiKwIxJd0Wc3QIDAQAB";


    public static void main(String[] args) throws Exception {

        /**
         * 上游平台公钥进行加密
         */
        PublicKey _PUBLIC_KEY = getPublicKey(platform_public_key);
        /**
         * 自己的私钥进行签名
         */
        PrivateKey _PRIVATE_KEY = getPrivateKey(private_key);

        pay(_PUBLIC_KEY, _PRIVATE_KEY);

        //query(_PUBLIC_KEY, _PRIVATE_KEY);

    }

    private static void pay(PublicKey _PUBLIC_KEY, PrivateKey _PRIVATE_KEY) throws Exception {
        String reqNo = getReqNo();

        ClientRequestData requestData = new ClientRequestData();
        requestData.setReqNo(reqNo);
        requestData.setOrgNo("1000001");

        TradeDetail tradeDetail = new TradeDetail();
        tradeDetail.setReqNo(reqNo);
        tradeDetail.setOrgUsrNo("1000001");
        //TODO 填入银行卡号和姓名
        tradeDetail.setBnkOac("********"); //银行卡号
        tradeDetail.setBnkAcnm("***");  //卡号姓名
        tradeDetail.setTrdTxnAmt(10L);   //提现金额（分）
        tradeDetail.setNotifyUrl(svr_url + "/notify_test");

        // 进行数据加密和签名
        String payload = JsonUtils.toJson(tradeDetail);
        String encPayloadBase64 = Base64.encode(RSAHelper.encrypt(_PUBLIC_KEY, payload.getBytes(StandardCharsets.UTF_8)));
        String signatureBase64 = Base64.encode(RSAHelper.sign(_PRIVATE_KEY, payload.getBytes(StandardCharsets.UTF_8)));
        requestData.setPayload(encPayloadBase64);
        requestData.setSignature(signatureBase64);

        String respBody = HttpClientFactory.getInstance().postForJson(svr_url + "/pay", JsonUtils.toJson(requestData));
        System.out.println(respBody);
        ClientResponseData respData = JsonUtils.fromJson(respBody, ClientResponseData.class);

        //解密
        String encryptedRespBase64 = respData.getPayload();
        String signatureRespBase64 = respData.getSignature();
        byte[] plainBytes = RSAHelper.decrypt2Bytes(_PRIVATE_KEY, Base64.decode(encryptedRespBase64));
        byte[] signatureBytes = Base64.decode(signatureRespBase64);
        boolean ret = RSAHelper.verify(plainBytes, _PUBLIC_KEY, signatureBytes);
        printResult(respData, plainBytes, ret);
    }

    private static void printResult(ClientResponseData respData, byte[] plainBytes, boolean ret) {
        if (!ret) {
            System.out.println("验签失败");
        } else {
            System.out.println("验签成功");
            System.out.println("受理结果： " + respData.getState() + ", 描述码：" + respData.getRespCode() + ", 描述信息：" + respData.getRespMessage());
            // 受理成功后，处理代付结果
            if (ETranState.S.equals(respData.getState()) || ETranState.E.equals(respData.getState())) {
                String respPayload = new String(plainBytes, StandardCharsets.UTF_8);
                System.out.println("原始数据： " + respPayload);
                TradeDetail respDetail = JsonUtils.fromJson(respPayload, TradeDetail.class);
                System.out.println("代付交易结果： " + respDetail.getTrdRspSts() + ", 描述码：" + respDetail.getTrdRspCd() + ", 描述信息：" + respDetail.getTrdRspMsg());
            }
        }
    }


    private static void query(PublicKey _PUBLIC_KEY, PrivateKey _PRIVATE_KEY) throws Exception {
        String reqNo = getReqNo();

        ClientRequestData requestData = new ClientRequestData();
        requestData.setReqNo(reqNo);
        requestData.setOrgNo("1000001");

        TradeDetail tradeDetail = new TradeDetail();
        tradeDetail.setReqNo(reqNo);
        tradeDetail.setDwnTrdNo("ID2018102418514873");
        //tradeDetail.setTrdDt("20180816");

        // 进行数据加密和签名
        String payload = JsonUtils.toJson(tradeDetail);
        String encPayloadBase64 = Base64.encode(RSAHelper.encrypt(_PUBLIC_KEY, payload.getBytes(StandardCharsets.UTF_8)));
        String signatureBase64 = Base64.encode(RSAHelper.sign(_PRIVATE_KEY, payload.getBytes(StandardCharsets.UTF_8)));
        requestData.setPayload(encPayloadBase64);
        requestData.setSignature(signatureBase64);


        String respBody = HttpClientFactory.getInstance().postForJson(svr_url + "/query", JsonUtils.toJson(requestData));
        System.out.println(respBody);
        ClientResponseData respData = JsonUtils.fromJson(respBody, ClientResponseData.class);

        //解密
        String encryptedRespBase64 = respData.getPayload();
        String signatureRespBase64 = respData.getSignature();
        byte[] plainBytes = RSAHelper.decrypt2Bytes(_PRIVATE_KEY, Base64.decode(encryptedRespBase64));
        byte[] signatureBytes = Base64.decode(signatureRespBase64);
        boolean ret = RSAHelper.verify(plainBytes, _PUBLIC_KEY, signatureBytes);
        printResult(respData, plainBytes, ret);
    }

    private static String getReqNo() {
        Date curDate = new Date();
        String strCurDate = DateTimeUtils.formatDateToString(curDate, DateTimeUtils.YYYYMMDDHHMMSSSS);
        return "ID" + strCurDate;
    }

}
